package com.hunttown.mes.service;

import com.hunttown.mes.common.utils.DateConvertUtils;
import com.hunttown.mes.common.utils.FormatUtils;
import com.hunttown.mes.common.utils.StringUtils;
import com.hunttown.common.domain.Query;
import com.hunttown.mes.domain.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.*;

/**
 * 事务层
 * created by wangjunfu on 2019/8/9
 */
@Service
public class TransactionManagerService {
    private final static Logger logger = LoggerFactory.getLogger(TransactionManagerService.class);

    private final WorkflowBusinessService businessService;
    private final WorkflowBusinessNodeService nodeService;
    private final WorkflowBusinessUserRelService businessUserRelService;
    private final WorkflowApplyService applyService;
    private final WorkflowApplyLineService applyLineService;
    private final WorkflowApplyLineUserService lineUserService;
    private final TransportDepartmentService departmentService;
    private final TransportInvoiceService invoiceService;
    private final TransportExpenseService expenseService;
    private final TransportPurchaseInventoryService inventoryService;
    private final TransportPurchaseInventoryDetailService inventoryDetailService;
    private final TransportPurchaseDocService purchaseDocService;
    private final TransportPurchaseOutService purchaseOutService;
    private final TransportPurchaseDetailService purchaseDetailService;
    private final TransportTableChineseEnglishService chineseEnglishService;
    private final TransportUserService userService;
    private final TransportManageDepRelService manageDepRelService;
    private final TransportManageRoleRelService manageRoleRelService;
    private final MesSaleOrderService mesSaleOrderService;
    private final MesSaleOrderDetailService mesSaleOrderDetailService;
    private final MesOrderMaterialService mesOrderMaterialService;
    private final MesProduceOrderService mesProduceOrderService;
    private final MesProduceOrderSaleService mesProduceOrderSaleService;

    @Autowired
    public TransactionManagerService(WorkflowBusinessService businessService, WorkflowBusinessNodeService nodeService, WorkflowBusinessUserRelService businessUserRelService, WorkflowApplyService applyService, WorkflowApplyLineService applyLineService, WorkflowApplyLineUserService lineUserService, TransportDepartmentService departmentService, TransportInvoiceService invoiceService, TransportExpenseService expenseService, TransportPurchaseInventoryService inventoryService, TransportPurchaseInventoryDetailService inventoryDetailService, TransportPurchaseDocService purchaseDocService, TransportPurchaseOutService purchaseOutService, TransportPurchaseDetailService purchaseDetailService, TransportTableChineseEnglishService chineseEnglishService, TransportUserService userService, TransportManageDepRelService manageDepRelService, TransportManageRoleRelService manageRoleRelService, MesSaleOrderService mesSaleOrderService, MesSaleOrderDetailService mesSaleOrderDetailService, MesOrderMaterialService mesOrderMaterialService, MesProduceOrderService mesProduceOrderService, MesProduceOrderSaleService mesProduceOrderSaleService){
        this.businessService = businessService;
        this.nodeService = nodeService;
        this.businessUserRelService = businessUserRelService;
        this.applyService = applyService;
        this.applyLineService = applyLineService;
        this.lineUserService = lineUserService;
        this.departmentService = departmentService;
        this.invoiceService = invoiceService;
        this.expenseService = expenseService;
        this.inventoryService = inventoryService;
        this.inventoryDetailService = inventoryDetailService;
        this.purchaseDocService = purchaseDocService;
        this.purchaseOutService = purchaseOutService;
        this.purchaseDetailService = purchaseDetailService;
        this.chineseEnglishService = chineseEnglishService;
        this.userService = userService;
        this.manageDepRelService = manageDepRelService;
        this.manageRoleRelService = manageRoleRelService;
        this.mesSaleOrderService = mesSaleOrderService;
        this.mesSaleOrderDetailService = mesSaleOrderDetailService;
        this.mesOrderMaterialService = mesOrderMaterialService;
        this.mesProduceOrderService = mesProduceOrderService;
        this.mesProduceOrderSaleService = mesProduceOrderSaleService;
    }

    //region 生成流程审批单

    //region 生成主流程

    /**
     * 创建流程
     *
     * @param businessName 流程业务英文名称
     * @param tableName    数据表名称：不同表代表不同的流程类型 例如：car_repair代表维修流程
     * @param recordId     记录ID
     * @param createPeople 创建人ID
     * @param map          扩展参数
     * @return 创建流程主ID
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Integer createApplyWithout(String businessName, String tableName, Integer recordId, Integer createPeople, Map<String, String> map) {

        //String preTitle,流程申请标题前缀

        try {
            if (StringUtils.isBlank(businessName) || StringUtils.isBlank(tableName) || recordId <= 0 || createPeople <= 0) {
                return 0;
            }

            //region STEP 01 获取流程信息

            // 获取中英文表信息
            TransportTableChineseEnglish englishDTO = chineseEnglishService.getByTableName(tableName);
            if (englishDTO == null) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return 0;
            }

            // 获取业务流程信息
            WorkflowBusiness businessDTO = businessService.getByEnName(businessName);
            if (businessDTO == null) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return 0;
            }

            // 插入主流程
            WorkflowApply applyDTO = new WorkflowApply();
            applyDTO.setBusinessId(businessDTO.getId());

            // 参数中是否包含审批标题
            String applyTitle = map.get("applyTitle");
            if (StringUtils.isNotBlank(applyTitle)) {
                applyDTO.setApplyTitle(applyTitle);
            } else {
                String preTitle = map.get("preTitle");
                applyDTO.setApplyTitle(String.format("%s的%s申请", preTitle, businessDTO.getBusinessName()));
            }

            applyDTO.setApplyType(0);
            applyDTO.setApply(createPeople);
            applyDTO.setApplyTime(new Date());
            applyDTO.setReviewer(0);
            applyDTO.setReviewTime(DateConvertUtils.strToDate("1990-01-01"));
            applyDTO.setTableId(englishDTO.getId());
            applyDTO.setRecordId(recordId);
            applyDTO.setStatus(0);
            applyDTO.setRemark("");
            applyDTO.setAdminId(createPeople);
            applyDTO.setCreateTime(new Date());
            applyDTO.setStopFlag(0);
            applyDTO.setDeleteFlag(0);
            applyDTO = applyService.insert(applyDTO);

            if (applyDTO == null || applyDTO.getId() == 0) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return 0;
            }
            //endregion

            //region STEP 02 获取流程节点信息

            Boolean isNext = insertWfLine(businessDTO.getId(), applyDTO.getId(), createPeople, map);
            if (!isNext) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return 0;
            }

            //endregion

            //操作成功 返回流程主ID
            return applyDTO.getId();

        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return 0;
        }
    }
    //endregion

    //region 创建流程（生成环节）

    /**
     * 创建流程（生成环节）
     *
     * @param businessId   流程业务ID
     * @param applyId      审批ID
     * @param createPeople 流程创建人
     * @param map          参数
     * @return true成功 false失败
     */
    public Boolean insertWfLine(Integer businessId, Integer applyId, Integer createPeople, Map<String, String> map) {

        //region STEP 02 获取流程节点信息
        Query query = Query.noPage();
        query.put("businessId", businessId);
        query.put("orderBy", "order by node_sort asc");
        List<WorkflowBusinessNode> nodePage = nodeService.selectByQuery(query);
        if (nodePage == null || nodePage.size() == 0) {
            return false;
        }

        WorkflowApplyLine lineDTO;
        Integer _prenode = 0;
        for (WorkflowBusinessNode item : nodePage) {
            lineDTO = new WorkflowApplyLine();
            lineDTO.setApplyId(applyId);
            lineDTO.setBusinessId(businessId);
            lineDTO.setNodeId(item.getId());
            lineDTO.setNodeTitle(item.getNodeTitle());
            lineDTO.setNodeDescription(item.getNodeDescription());
            lineDTO.setNodeSort(item.getNodeSort());
            lineDTO.setNodeSign(item.getNodeSort());
            lineDTO.setApprovalType(item.getApprovalType());
            lineDTO.setApplyType(item.getApplyType());

            //替换审批/代理人前要先给默认值
            lineDTO.setApprover(0); //废弃
            lineDTO.setAgentId(0);  //废弃
            lineDTO.setApproverReplace(0);//废弃
            lineDTO.setAgentReplace(0);   //废弃

            //替换审批/代理人，注意位置
            //lineDTO = replaceApproveId(lineDTO, map); //废弃

            lineDTO.setIsAuto(item.getIsAuto());
            lineDTO.setIsInitiatorApprover(0);  //废弃
            lineDTO.setIsRejected(item.getIsRejected());
            lineDTO.setIsRecall(item.getIsRecall());
            lineDTO.setIsJudge(item.getIsJudge());
            lineDTO.setJudgeData(item.getJudgeData());
            lineDTO.setJudgeDescription(item.getJudgeDescription());
            lineDTO.setIsDriverApply(0);  //废弃
            lineDTO.setIsUserApply(0);    //废弃
            lineDTO.setIsBack(item.getIsBack());
            lineDTO.setBackType(item.getBackType());
            lineDTO.setBackSubmit(item.getBackSubmit());
            lineDTO.setIsCanBack(item.getIsCanBack());
            lineDTO.setIsAdd(item.getIsAdd());
            lineDTO.setIsUrge(item.getIsUrge());

            lineDTO.setIsCurrent(_prenode == 0 ? 1 : 0);
            lineDTO.setRealApproverId(0);
            lineDTO.setRealApproverTime(DateConvertUtils.strToShortDate("1990-01-01"));
            lineDTO.setStatus(0);
            lineDTO.setRecordStatus(item.getRecordStatus());
            lineDTO.setRejectStatus(item.getRejectStatus());
            lineDTO.setRemark("");
            lineDTO.setPreNode(_prenode);
            lineDTO.setNextNode(0);
            lineDTO.setAdminId(createPeople);
            lineDTO.setStopFlag(0);
            lineDTO.setDeleteFlag(0);
            lineDTO = applyLineService.insert(lineDTO);

            if (lineDTO == null || lineDTO.getId() == 0) {
                return false;
            }

            //更新上一个环节的nextnode
            if (_prenode > 0) {
                WorkflowApplyLine lastdto = new WorkflowApplyLine();
                lastdto.setId(_prenode);
                lastdto.setNextNode(lineDTO.getId());
                Boolean isNext = applyLineService.updateInfoById(lastdto);
                if (!isNext) {
                    return false;
                }
            }

            //插入审批人关联表
            insertWfLineUser(item.getId(), applyId, lineDTO.getId(), map);

            //更新prenode为当前id
            _prenode = lineDTO.getId();
        }
        //endregion

        return true;
    }
    //endregion

    //region 生成环节审批人关联表

    /**
     * 生成环节审批人关联表
     *
     * @param nodeId  配置中的流程节点ID
     * @param applyId 生成的流程ID
     * @param lineId  生成的环节ID
     * @param map     参数集合
     */
    private void insertWfLineUser(Integer nodeId, Integer applyId, Integer lineId, Map<String, String> map) {

        //取出环节审批人配置
        Query query = Query.noPage();
        query.put("nodeId", nodeId);
        List<WorkflowBusinessUserRel> relList = businessUserRelService.selectByQuery(query);

        //获取申请人，复核人
        Integer firstExector = map.get("firstExector") == null ? 0 : Integer.parseInt(map.get("firstExector"));
        Integer secondExector = map.get("secondExector") == null ? 0 : Integer.parseInt(map.get("secondExector"));

        //需要插入的对象
        WorkflowApplyLineUser insert;

        for (WorkflowBusinessUserRel item : relList) {
            insert = new WorkflowApplyLineUser();
            insert.setApplyId(applyId);
            insert.setLineId(lineId);
            insert.setUserType(item.getUserType());         //用户类型：1管理员 2司机 3会员（用于会员表判断）
            insert.setPlayerType(item.getPlayerType());     //人员类型：1审批人 2代理人 3抄送人
            insert.setApproverType(item.getApproverType()); //角色类型：1指定成员 2申请人 3复核人 4直属上级 5部门主管 6部门成员 7角色
            insert.setDepId(item.getDepId());
            insert.setRoleId(item.getRoleId());
            insert.setDeleteFlag(0);

            //region //替换数据中的参数
            //角色类型：1指定成员 2申请人 3复核人 4直属上级 5部门主管 6部门成员 7角色
            //endregion

            //region TYPE[01] 指定人员
            if (item.getApproverType() == 1) {
                insert.setApprover(item.getApprover());
                lineUserService.insert(insert);
                continue;
            }
            //endregion

            //region TYPE[02] 申请人
            if (item.getApproverType() == 2) {
                insert.setApprover(firstExector);
                lineUserService.insert(insert);
                continue;
            }
            //endregion

            //region TYPE[03] 复核人
            if (item.getApproverType() == 3) {
                insert.setApprover(secondExector);
                lineUserService.insert(insert);
                continue;
            }
            //endregion

            //region TYPE[04] 直属上级[部门主管]
            if (item.getApproverType() == 4) {
                List<Integer> depIds = new ArrayList<>();

                //两种情况：1是指定了部门；2未指定，跟随申请人的部门
                if (item.getDepId() > 0) {
                    //直接使用指定部门
                    depIds.add(item.getDepId());
                } else {
                    //通过申请人（会员）获取其所属部门
                    depIds = get_depid(firstExector);
                }

                //将部门主管逐个插入
                for (Integer dep_id : depIds) {
                    ins_approve(insert, dep_id, 1);
                }

                continue;
            }
            //endregion

            //region TYPE[05] 部门主管[顶级]
            if (item.getApproverType() == 5) {

                //两种情况：1是指定了部门；2未指定，跟随申请人的部门
                if (item.getDepId() > 0) {
                    //直接使用指定部门
                    ins_approve(insert, item.getDepId(), 1);

                } else {
                    //通过申请人（会员）获取其所属部门
                    List<Integer> depIds = get_depid(firstExector);

                    //将部门主管逐个插入（会出现一个人身兼多个部门的情况）
                    for (Integer dep_id : depIds) {
                        //此处与TYPE[4]不同，需要获取顶级ID
                        int rootid = departmentService.getRootIdByRecursion(dep_id);
                        ins_approve(insert, rootid, 1);
                    }
                }

                continue;
            }
            //endregion

            //region TYPE[06] 部门成员
            if (item.getApproverType() == 6) {
                List<Integer> depIds = new ArrayList<>();

                //两种情况：1是指定了部门；2未指定，跟随申请人的部门
                if (item.getDepId() > 0) {
                    //直接使用指定部门
                    depIds.add(item.getDepId());
                } else {
                    //通过申请人（会员）获取其所属部门
                    depIds = get_depid(firstExector);
                }

                //将部门成员逐个插入
                for (Integer dep_id : depIds) {
                    ins_approve(insert, dep_id, -1);
                }

                continue;
            }
            //endregion

            //region TYPE[07] 角色
            if (item.getApproverType() == 7) {
                //取出角色下的所有成员
                Query jueseQuery = Query.noPage();
                jueseQuery.put("tableId", 13);
                jueseQuery.put("roleId", item.getRoleId());
                List<TransportManageRoleRel> chengyuanList = manageRoleRelService.selectByQuery(jueseQuery);

                for (TransportManageRoleRel chengyuan : chengyuanList) {
                    //通过管理员ID获取会员ID
                    Query userQuery = Query.noPage();
                    userQuery.put("manageId", chengyuan.getRecordId());
                    userQuery.put("stopFlag", 0);
                    TransportUser user = userService.selectObjByQuery(userQuery);

                    if (user != null) {
                        insert.setId(null);
                        insert.setApprover(user.getId());
                        lineUserService.insert(insert);
                    }
                }
            }
            //endregion

        }
    }

    //重复代码，提出来公用（查询部门ID）
    private List<Integer> get_depid(Integer userid) {
        //返回结果
        List<Integer> depIds = new ArrayList<>();

        //通过申请人（会员）获取管理员ID
        TransportUser firstUser = userService.selectById(userid);

        if (firstUser == null) {
            return depIds;
        }

        //这里会出现两种情况：管理员和司机（管理员优先）
        if (firstUser.getManageId() > 0) {
            //【管理员】 取出他所在部门ID集合
            Query depQuery = Query.noPage();
            depQuery.put("tableId", 13);
            depQuery.put("recordId", firstUser.getManageId());
            List<TransportManageDepRel> depList = manageDepRelService.selectByQuery(depQuery);

            for (TransportManageDepRel dep : depList) {
                if (!depIds.contains(dep.getDepId())) {
                    depIds.add(dep.getDepId());
                }
            }
        }

        return depIds;
    }

    //重复代码，提出来公用
    private void ins_approve(WorkflowApplyLineUser insert, Integer depid, Integer dutyid) {
        if (depid <= 0) {
            return;
        }

        //取出本部门主管
        Query zhuguanQuery = Query.noPage();
        zhuguanQuery.put("tableId", 13);
        zhuguanQuery.put("depId", depid);
        if (dutyid >= 0) {
            zhuguanQuery.put("dutyId", dutyid);
        }
        List<TransportManageDepRel> zhuguanList = manageDepRelService.selectByQuery(zhuguanQuery);

        for (TransportManageDepRel zhuguan : zhuguanList) {
            //通过管理员ID获取会员ID
            Query userQuery = Query.noPage();
            userQuery.put("manageId", zhuguan.getRecordId());
            userQuery.put("stopFlag", 0);
            TransportUser user = userService.selectObjByQuery(userQuery);

            if (user != null) {
                insert.setId(null);
                insert.setApprover(user.getId());
                lineUserService.insert(insert);
            }
        }
    }
    //endregion

    //region 修改审批单后，替换流程环节中审批人关联表中的相关审批人

    /**
     * 修改审批单后，替换流程环节中审批人关联表中的相关审批人
     *
     * @param applyId 流程业务ID
     * @param map     要替换的ID，如：1.申请人、2.复核人、3.司机、4.会员
     */
    public void setExector(Integer applyId, Map<Integer, Integer> map) {
        if (applyId == null || applyId <= 0) {
            return;
        }

        //获取申请人，复核人
        Integer firstExector = (map.get(1) == null) ? 0 : map.get(1);
        Integer secondExector = (map.get(2) == null) ? 0 : map.get(2);

        //获取审批环节
        Query query = Query.noPage();
        query.put("applyId", applyId);
        List<WorkflowApplyLine> page = applyLineService.selectByQuery(query);

        for (WorkflowApplyLine item : page) {
            if (item.getStatus() != 0) { //已经审批过了
                continue;
            }

            //获取审批环节的审批人关联表
            Query relQuery = Query.noPage();
            relQuery.put("lineId", item.getId());
            List<WorkflowApplyLineUser> relList = lineUserService.selectByQuery(relQuery);

            //更新的对象
            WorkflowApplyLineUser updatedto = null;

            for (WorkflowApplyLineUser child : relList) {
                //角色类型：1指定成员 2申请人 3复核人 4直属上级 5部门主管 6部门成员 7角色
                if (child.getApproverType() == 2) {
                    updatedto = new WorkflowApplyLineUser();
                    updatedto.setApprover(firstExector);
                }

                if (child.getApproverType() == 3) {
                    updatedto = new WorkflowApplyLineUser();
                    updatedto.setApprover(secondExector);
                }

                if (updatedto != null) {
                    updatedto.setId(child.getId());
                    lineUserService.updateInfoById(updatedto);
                }
            }
        }
    }
    //endregion

    //endregion

    //region 设置流程审批环节中：经理（领导）审批是否为自动审批

    /**
     * 设置流程审批环节中：经理（领导）审批是否为自动审批
     *
     * @param applyId  审批ID
     * @param nodeSort 环节序号：如果有两个审批呢？比如请假超过3天需要主管审批，超过5天需要总监审批
     * @param isAuto   是否自动审批 1是0否
     */
    public void setManageApply(Integer applyId, Integer nodeSort, Integer isAuto) {
        if (applyId == null || applyId <= 0) {
            return;
        }
        if (isAuto == null || isAuto <= 0) {
            isAuto = 0;
        }
        if (isAuto > 1) {
            isAuto = 1;
        }

        Query query = Query.noPage();
        query.put("applyId", applyId);
        List<WorkflowApplyLine> page = applyLineService.selectByQuery(query);

        for (WorkflowApplyLine item : page) {
            //已经审批的，直接跳过
            if (item.getStatus() != 0) {
                continue;
            }

            //当前环节启用：条件审批
            if (item.getNodeSort().equals(nodeSort) && item.getIsJudge() == 1) {
                WorkflowApplyLine updto = new WorkflowApplyLine();
                updto.setId(item.getId());
                updto.setIsAuto(isAuto);
                applyLineService.updateInfoById(updto);
            }
        }
    }

    //endregion

    //region 流程审批

    /**
     * 流程审批
     *
     * @param id         环节id
     * @param status     审批状态 -10撤回 1通过 -1驳回 -2回退
     * @param remark     审批意见
     * @param approvel   审批人（新版改为会员）
     * @param addApprove 加签审批人（新版改为会员）
     * @param backLineId 回退ID
     * @return tf
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean approvelApply(Integer id, Integer status, String remark, Integer approvel, Integer addApprove, Integer backLineId) {
        try {
            if (id == null || id == 0 || approvel == null || approvel == 0) {
                return false;
            }

            //region STEP 01 - 03、07. 审批
            Boolean isNext = applyLineService.changeState(id, status, remark, approvel);
            if (!isNext) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return false;
            }

            //region STEP 07.回退（首先删掉当前环节以后的环节，然后把回退环节及以后的环节重新插入）
            if (status == -2 && backLineId != null && backLineId > 0) {
                isNext = backOffApply(id, backLineId);
                if (!isNext) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return false;
                } else {
                    return isNext;
                }
            }
            //endregion

            WorkflowApplyLine line_dto = applyLineService.selectById(id);    //当前节点实体类
            WorkflowApplyLine next_dto = null;   //下一个节点实体类
            boolean last_node = true;

            if (line_dto.getNextNode() > 0) {
                last_node = false;

                //region STEP 02 - 03. 更新下一个节点为当前节点（撤销、驳回就不更新了）
                if (status == 1) {
                    WorkflowApplyLine obj = new WorkflowApplyLine();
                    obj.setIsCurrent(1);
                    obj.setId(line_dto.getNextNode());
                    Boolean isNext2 = applyLineService.updateInfoById(obj);
                    if (!isNext2) {
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        return false;
                    }

                    //region STEP 03. 判断下一个节点是否是“自动节点”，如果“是”则自动审批。
                    next_dto = applyLineService.selectById(line_dto.getNextNode());
                    if (next_dto != null) {
                        if (next_dto.getIsAuto() == 1) {
                            //递归调用
                            approvelApply(next_dto.getId(), 1, "系统自动审批", 1, addApprove, backLineId);
                        }
                    }
                    //endregion
                }
                //endregion
            }
            //endregion

            //region STEP 04. 更新主流程状态（最后一个节点更新，或者是撤销、驳回时更新）
            if (last_node || status == -10 || status == -1) {
                WorkflowApply apply_obj = new WorkflowApply();
                apply_obj.setStatus(status);
                apply_obj.setId(line_dto.getApplyId());
                Boolean isNext3 = applyService.updateInfoById(apply_obj);
                if (!isNext3) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return false;
                }
            }
            //endregion

            //region STEP 05. 更新业务状态
            WorkflowApply applyDTO = applyService.selectById(line_dto.getApplyId());

            //根据tableid获取tablename
            TransportTableChineseEnglish englishDTO = chineseEnglishService.selectById(applyDTO.getTableId());
            if (englishDTO == null) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return false;
            }

            //region [3].报销单
            if (englishDTO.getTableName().toLowerCase().equals("transport_expense")) {
                Boolean LastRes = expenseApply(applyDTO, line_dto, next_dto, status);
                if (!LastRes) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return false;
                }
            }
            //endregion

            //region [4].物料盘点单
            if (englishDTO.getTableName().toLowerCase().equals("transport_purchase_inventory")) {
                Boolean LastRes = inventoryApply(applyDTO, line_dto, next_dto, status);
                if (!LastRes) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return false;
                }
            }
            //endregion

            //region [5].物料审批（物料领用、物料损坏、无单出库）
            if (englishDTO.getTableName().toLowerCase().equals("transport_purchase_detail")) {
                Boolean LastRes = purchaseApply(applyDTO, line_dto, next_dto, status);
                if (!LastRes) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return false;
                }
            }
            //endregion

            //region [8].采购单
            if (englishDTO.getTableName().toLowerCase().equals("transport_purchase_doc")) {
                Boolean LastRes = purchaseDocApply(applyDTO, line_dto, next_dto, status);
                if (!LastRes) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return false;
                }
            }
            //endregion

            //region [9].出库单
            if (englishDTO.getTableName().toLowerCase().equals("transport_purchase_out")) {
                Boolean LastRes = purchaseOutApply(applyDTO, line_dto, next_dto, status);
                if (!LastRes) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return false;
                }
            }
            //endregion

            //region [10].销售订单
            if (englishDTO.getTableName().toLowerCase().equals("mes_sale_order")) {
                Boolean LastRes = saleOrderApply(applyDTO, line_dto, next_dto, status);
                if (!LastRes) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return false;
                }
            }
            //endregion

            //region [11].生产订单审批
            if (englishDTO.getTableName().toLowerCase().equals("mes_produce_order")) {
                Boolean LastRes = produceOrderApply(applyDTO, line_dto, next_dto, status);
                if (!LastRes) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return false;
                }
            }
            //endregion

            //endregion

            //region STEP 06. 加签处理
            if (status == 1 && addApprove != null && addApprove > 0) {

                //1-1.先取出当前【环节】信息
                WorkflowApplyLine curr_dto = applyLineService.selectById(id);
                if (curr_dto == null) {
                    return true;
                }

                //2-1.再取出剩下的【环节】
                Query query = Query.noPage();
                query.put("applyId", curr_dto.getApplyId());
                query.put("afterNodeSort", curr_dto.getNodeSort() + 1);
                List<WorkflowApplyLine> last_page = applyLineService.selectByQuery(query);

                //2-2.插入加签【环节】信息
                curr_dto.setId(null);
                if (StringUtils.isNotBlank(curr_dto.getNodeDescription())) {
                    if (!curr_dto.getNodeDescription().contains("加签")) {
                        curr_dto.setNodeDescription(curr_dto.getNodeDescription() + "（加签）");
                    }
                } else {
                    if (!curr_dto.getNodeTitle().contains("加签")) {
                        curr_dto.setNodeTitle(curr_dto.getNodeTitle() + "（加签）");
                    }
                }
                curr_dto.setNodeSort(curr_dto.getNodeSort() + 1);
                curr_dto.setIsCurrent(1);
                curr_dto.setApprover(addApprove);
                curr_dto.setRealApproverId(0);
                curr_dto.setRealApproverTime(DateConvertUtils.strToDate("1990-01-01"));
                curr_dto.setStatus(0);
                curr_dto.setRemark("");
                curr_dto.setPreNode(curr_dto.getPreNode() + 1);
                curr_dto = applyLineService.insert(curr_dto);

                //2-3.把未完成的【环节】顺序后延
                for (WorkflowApplyLine item : last_page) {
                    if (Objects.equals(curr_dto.getNextNode(), item.getId())) {
                        item.setPreNode(curr_dto.getId());
                    }
                    item.setIsCurrent(0);
                    item.setNodeSort(item.getNodeSort() + 1);
                    applyLineService.updateInfoById(item);
                }

                //3-1.直接插入一个【指定审批人】的【关联人】
                WorkflowApplyLineUser newdto = new WorkflowApplyLineUser();
                newdto.setApplyId(line_dto.getApplyId());
                newdto.setLineId(curr_dto.getId());
                newdto.setUserType(3);
                newdto.setPlayerType(1);
                newdto.setApproverType(1);
                newdto.setDepId(0);
                newdto.setApprover(addApprove);
                newdto.setDeleteFlag(0);
                lineUserService.insert(newdto);

            }
            //endregion

            return true;
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }
    }

    //回退流程（首先删掉当前环节以后的环节，然后把回退环节及以后的环节重新插入）
    private boolean backOffApply(Integer lineId, Integer backLineId) {
        boolean isNext = true;

        //当前环节
        WorkflowApplyLine lineDto = applyLineService.selectById(lineId);
        WorkflowApplyLine backLineDto = applyLineService.selectById(backLineId);

        //1-1.取出【当前】环节以后所有的【环节】，不含当前环节
        Query currQuery = Query.noPage();
        currQuery.put("applyId", lineDto.getApplyId());
        currQuery.put("afterNodeSort", lineDto.getNodeSort() + 1);
        List<WorkflowApplyLine> currList = applyLineService.selectByQuery(currQuery);

        //2-1.取出【回退】环节及以后的【环节】，含回退环节
        Query backQuery = Query.noPage();
        backQuery.put("applyId", lineDto.getApplyId());
        backQuery.put("afterNodeSort", backLineDto.getNodeSort());
        backQuery.put("orderBy", "order by node_sort asc"); //有加签流程
        List<WorkflowApplyLine> backList = applyLineService.selectByQuery(backQuery);

        //2-2.取出【回退】环节及以后的【关联人】，含加退环节
        Query backRelQuery = Query.noPage();
        backRelQuery.put("applyId", lineDto.getApplyId());
        backRelQuery.put("afterLine", backLineId);
        List<WorkflowApplyLineUser> backRelList = lineUserService.selectByQuery(backRelQuery);

        //1-2.删除1-1的数据（注意执行顺序，只能放到这个位置执行）
        for (WorkflowApplyLine item : currList) {
            applyLineService.deleteById(item.getId());
        }

        //这个是当前环节的顺序，后面插入的顺序都自动+1
        int nodeSort = lineDto.getNodeSort();
        int preNode = lineId;
        Date date = DateConvertUtils.strToDate("1990-01-01");

        //如果回退过一次，再次回退的话就会产生重复的节点，做一下过滤
        List<Integer> insNodeSign = new ArrayList<>();

        //2-3.重新插入2-1数据，同时插入2-2的数据
        for (WorkflowApplyLine item : backList) {
            if (insNodeSign.contains(item.getNodeSign())) {
                continue;
            } else {
                insNodeSign.add(item.getNodeSign());
            }

            nodeSort++;

            //先把关联人拿出来，否则后面ID会被覆盖 backRelList.stream().filter(s->s.getLineId().equals(item.getId())).collect(Collectors.toList());
            List<WorkflowApplyLineUser> rel = new ArrayList<>();
            for (WorkflowApplyLineUser s : backRelList) {
                if (s.getLineId().equals(item.getId())) {
                    rel.add(s);
                }
            }

            //先赋值，下面可能会被覆盖
            if (item.getNodeSort().equals(backLineDto.getNodeSort())) {
                item.setIsCurrent(1);
            }

            item.setId(0);
            item.setNodeSort(nodeSort);
            item.setRealApproverId(0);
            item.setRealApproverTime(date);
            item.setPeopleName("");
            item.setStatus(0);
            item.setRemark("");
            item.setPreNode(preNode);
            item.setNextNode(0);
            item = applyLineService.insert(item);

            if (item != null && item.getId() > 0) {
                //插入成功
                //[1].更新上一个环节的[下一个环节]
                WorkflowApplyLine update = new WorkflowApplyLine();
                update.setId(preNode);
                update.setNextNode(item.getId());
                isNext = applyLineService.updateInfoById(update);
                if (!isNext) {
                    break;
                }

                //[2].插入审批关联人
                for (WorkflowApplyLineUser ins : rel) {
                    ins.setId(0);
                    ins.setLineId(item.getId());
                    ins = lineUserService.insert(ins);
                    if (ins == null || ins.getId() == null || ins.getId() <= 0) {
                        isNext = false;
                        break;
                    }
                }

                //[3].更新preNode
                preNode = item.getId();

            } else {
                //插入失败，直接回滚
                isNext = false;
                break;
            }
        }

        return isNext;
    }
    //endregion

    //region 审批自动处理业务封装

    //region [3].报销单
    private Boolean expenseApply(WorkflowApply applyDTO, WorkflowApplyLine line_dto, WorkflowApplyLine next_dto, Integer status) {
        Boolean isNext = true;

        //报销类型：1司机费用 2采购报销 3配件报销 4维修报销 5综合报销 6借款申请 7费用支付

        //报销流程
        TransportExpense dto = expenseService.selectById(applyDTO.getRecordId());
        if (dto != null) {

            TransportExpense updateDTO = new TransportExpense();
            updateDTO.setId(applyDTO.getRecordId());

            //[1]. 判断状态：正常审批/驳回/撤回
            if (status == 1) {
                //正常审批
                if (next_dto != null) {
                    //这里为什么要更新为下一个节点的状态？
                    //因为当前状态已经审批完了，要给用户展示的是下一个节点的信息
                    updateDTO.setBxStatus(next_dto.getRecordStatus());
                } else {
                    //最后一个状态为自动节点，审批完更新为当前节点状态即可
                    updateDTO.setBxStatus(line_dto.getRecordStatus());
                }

            } else if (status == -1) {
                //驳回
                updateDTO.setBxStatus(line_dto.getRejectStatus());

            } else if (status == -10) {
                //撤回
                updateDTO.setBxStatus(-10);
                updateDTO.setStopFlag(1);

            } else {
                //TODO
            }

            //[2]. 更新状态：正常审批/驳回/撤回
            if (status == 1 || status == -1 || status == -10) {
                isNext = expenseService.updateInfoById(updateDTO);
            }

            //[3-1]. 这里很重要：最后一个环节为“正常审批”时，要更新[报销订单表]的报销状态为[已报销]
            if (isNext && next_dto == null && status == 1) {

                //A.【司机报销】

                //B.【采购报销】【配件报销】
                if (dto.getBxType() == 2 || dto.getBxType() == 3) {
                    List<Integer> idList = FormatUtils.commaToList_Integer(dto.getBookidsArray());
                    if (idList.size() > 0) {
                        Query query = Query.noPage();
                        query.put("status", 1);
                        query.put("ids", idList);
                        isNext = purchaseDetailService.updateInfoByQuery(query);
                    }
                }

                //C.【借款申请】【费用支付】
                if (dto.getBxType() == 6 || dto.getBxType() == 7) {
                    //检查报销表中关联的 借款申请和费用支付，并将其更新为 已完成。
                    Query query = Query.noPage();
                    query.put("bxStatus", 2);
                    query.put("w_relationId", dto.getId());
                    expenseService.updateInfoByQuery(query);
                }
            }

            //[3-2]. 这里很重要：当审批为“驳回”、“撤回”时，恢复业务数据，还需要更新[行程订单表]的报销状态为[未报销]
            if (isNext && (status == -1 || status == -10)) {

                //A.【司机报销】（处理调度）

                //B.【采购报销】【配件报销】（处理采购明细）
                if (dto.getBxType() == 2 || dto.getBxType() == 3) {
                    List<Integer> idList = FormatUtils.commaToList_Integer(dto.getBookidsArray());
                    if (idList.size() > 0) {
                        Query query = Query.noPage();
                        query.put("bxId", 0);
                        query.put("ids", idList);
                        isNext = purchaseDetailService.updateInfoByQuery(query);
                    }
                }

                //将关联的【借款申请】【费用支付】[RELATION_ID]设置为0
                if (isNext) {
                    Query query = Query.noPage();
                    query.put("relationId", 0);
                    query.put("w_relationId", dto.getId());
                    expenseService.updateInfoByQuery(query);
                }
            }
        }

        return isNext;
    }

    //endregion

    //region [4].物料盘点单
    private Boolean inventoryApply(WorkflowApply applyDTO, WorkflowApplyLine line_dto, WorkflowApplyLine next_dto, Integer status) {
        Boolean isNext = true;

        //获取盘点信息
        TransportPurchaseInventory dto = inventoryService.selectById(applyDTO.getRecordId());
        if (dto != null) {

            TransportPurchaseInventory updateDTO = new TransportPurchaseInventory();
            updateDTO.setId(applyDTO.getRecordId());

            //[1]. 判断状态：正常审批/驳回/撤回
            if (status == 1) {
                //正常审批
                if (next_dto != null) {
                    //这里为什么要更新为下一个节点的状态？
                    //因为当前状态已经审批完了，要给用户展示的是下一个节点的信息
                    updateDTO.setStatus(next_dto.getRecordStatus());
                } else {
                    //最后一个状态为自动节点，审批完更新为当前节点状态即可
                    updateDTO.setStatus(line_dto.getRecordStatus());
                }

            } else if (status == -1) {
                //驳回
                updateDTO.setStatus(line_dto.getRejectStatus());

            } else if (status == -10) {
                //撤回
                updateDTO.setStatus(-10);
                updateDTO.setStopFlag(1);

            } else {
                //TODO
            }

            //[2]. 更新状态：正常审批/驳回/撤回
            if (status == 1 || status == -1 || status == -10) {
                isNext = inventoryService.updateInfoById(updateDTO);
            }

            //[3-1]. 这里很重要：最后一个环节为“正常审批”时，要更新库存数据，即将插入一条“损坏”记录，数值为：盈亏数，原因为：仓库盘点
            if (isNext && next_dto == null && status == 1) {
                //获取盘点明细
                Query query = Query.noPage();
                query.put("inventoryId", applyDTO.getRecordId());
                query.put("stopFlag", 0);
                List<TransportPurchaseInventoryDetail> dataPage = inventoryDetailService.selectByQuery(query);

                Date default_date = DateConvertUtils.strToDate("1990-01-01");

                TransportPurchaseDetail detail;
                for (TransportPurchaseInventoryDetail item : dataPage) {
                    if (item.getProfitLoss() != 0) {
                        detail = new TransportPurchaseDetail();
                        detail.setPartId(item.getPartId());
                        detail.setOpType(3);
                        detail.setrPurchaseDate(default_date);
                        detail.setrInDate(default_date);
                        detail.setcOutDate(default_date);
                        detail.setsCount(-item.getProfitLoss());
                        detail.setsReason(String.format("%s-%s仓库盘点", item.getpYear(), item.getpMonth()));
                        detail.setsAdminId(0);
                        detail.setsDate(default_date);
                        detail.setReviewer(0);
                        detail.setReviewDate(default_date);
                        detail.setReviewStatus(0);
                        detail.setStatus(1);
                        detail.setBxId(0);
                        detail.setApplyId(0);
                        detail.setRelationId(0);
                        detail.setAdminId(item.getInventory());
                        detail.setCreateTime(item.getInventoryDate());
                        detail.setStopFlag(0);
                        detail.setStopFlag(0);
                        purchaseDetailService.insert(detail);
                    }
                }
            }

            //[3-2]. 这里很重要：当审批为“驳回”、“撤回”时，还需要恢复[盘点明细表]的盘点单ID为[0]
            if (isNext && (status == -1 || status == -10)) {
                Query query = Query.noPage();
                query.put("inventoryId", 0);
                query.put("w_inventoryId", applyDTO.getRecordId());
                isNext = inventoryDetailService.updateInfoByQuery(query);
            }
        }

        return isNext;
    }
    //endregion

    //region [5].物料审批（物料领用、物料损坏、无单出库）
    private Boolean purchaseApply(WorkflowApply applyDTO, WorkflowApplyLine line_dto, WorkflowApplyLine next_dto, Integer status) {
        Boolean isNext = true;

        //获取采购明细信息（物料领用、物料损坏都是按明细计数的）
        TransportPurchaseDetail dto = purchaseDetailService.selectById(applyDTO.getRecordId());

        if (dto != null) {
            TransportPurchaseDetail updateDTO = new TransportPurchaseDetail();
            updateDTO.setId(applyDTO.getRecordId());

            //[1]. 判断状态：正常审批/驳回/撤回
            if (status == 1) {
                //正常审批
                if (next_dto != null) {
                    //这里为什么要更新为下一个节点的状态？
                    //因为当前状态已经审批完了，要给用户展示的是下一个节点的信息
                    updateDTO.setStatus(next_dto.getRecordStatus());
                } else {
                    //最后一个状态为自动节点，审批完更新为当前节点状态即可
                    updateDTO.setStatus(line_dto.getRecordStatus());
                }

            } else if (status == -1) {
                //驳回
                updateDTO.setStopFlag(1);
                updateDTO.setStatus(line_dto.getRejectStatus());

            } else if (status == -10) {
                //撤回
                updateDTO.setStatus(-10);
                updateDTO.setStopFlag(1);

            } else {
                //TODO
            }

            //[2]. 更新状态：正常审批/驳回/撤回
            if (status == 1 || status == -1 || status == -10) {
                isNext = purchaseDetailService.updateInfoById(updateDTO);
            }

            //[3]. 这里很重要：当审批为“驳回”、“撤回”时，恢复业务数据
            if (isNext && (status == -1 || status == -10)) {
                //TODO
            }
        }

        return isNext;
    }
    //endregion

    //region [8].采购单
    private Boolean purchaseDocApply(WorkflowApply applyDTO, WorkflowApplyLine line_dto, WorkflowApplyLine next_dto, Integer status) {
        Boolean isNext = true;

        //获取采购信息
        TransportPurchaseDoc dto = purchaseDocService.selectById(applyDTO.getRecordId());
        if (dto != null) {

            TransportPurchaseDoc updateDTO = new TransportPurchaseDoc();
            updateDTO.setId(applyDTO.getRecordId());

            //[1]. 判断状态：正常审批/驳回/撤回
            if (status == 1) {
                //正常审批
                if (next_dto != null) {
                    //这里为什么要更新为下一个节点的状态？
                    //因为当前状态已经审批完了，要给用户展示的是下一个节点的信息
                    updateDTO.setStatus(next_dto.getRecordStatus());
                } else {
                    //最后一个状态为自动节点，审批完更新为当前节点状态即可
                    updateDTO.setStatus(line_dto.getRecordStatus());
                }

            } else if (status == -1) {
                //驳回
                updateDTO.setStatus(line_dto.getRejectStatus());

            } else if (status == -10) {
                //撤回
                updateDTO.setStatus(-10);
                updateDTO.setStopFlag(1);

            } else {
                //TODO
            }

            //[2]. 更新状态：正常审批/驳回/撤回
            if (status == 1 || status == -1 || status == -10) {
                isNext = purchaseDocService.updateInfoById(updateDTO);
            }
        }

        return isNext;
    }
    //endregion

    //region [9].出库单
    private Boolean purchaseOutApply(WorkflowApply applyDTO, WorkflowApplyLine line_dto, WorkflowApplyLine next_dto, Integer status) {
        Boolean isNext = true;

        //获取出库信息
        TransportPurchaseOut dto = purchaseOutService.selectById(applyDTO.getRecordId());
        if (dto != null) {

            TransportPurchaseOut updateDTO = new TransportPurchaseOut();
            updateDTO.setId(applyDTO.getRecordId());

            //[1]. 判断状态：正常审批/驳回/撤回
            if (status == 1) {
                //正常审批
                if (next_dto != null) {
                    //这里为什么要更新为下一个节点的状态？
                    //因为当前状态已经审批完了，要给用户展示的是下一个节点的信息
                    updateDTO.setStatus(next_dto.getRecordStatus());
                } else {
                    //最后一个状态为自动节点，审批完更新为当前节点状态即可
                    updateDTO.setStatus(line_dto.getRecordStatus());
                }

            } else if (status == -1) {
                //驳回
                updateDTO.setStatus(line_dto.getRejectStatus());

            } else if (status == -10) {
                //撤回
                updateDTO.setStatus(-10);
                updateDTO.setStopFlag(1);

            } else {
                //TODO
            }

            //[2]. 更新状态：正常审批/驳回/撤回
            if (status == 1 || status == -1 || status == -10) {
                isNext = purchaseOutService.updateInfoById(updateDTO);
            }

            //[3]. 这里很重要：当审批为“驳回”、“撤回”时，将出库记录设为无效，否则影响统计
            if (isNext && (status == -1 || status == -10)) {
                Query query = Query.noPage();
                query.put("tableId", 205);
                query.put("purId", dto.getId());
                query.put("stopFlag", 0);
                List<TransportPurchaseDetail> childList = purchaseDetailService.selectByQuery(query);

                for (TransportPurchaseDetail item : childList) {
                    purchaseDetailService.deleteById(item.getId());

                    //如果是子出库单，还要恢复主单中的数据
                    if (dto.getParentId() > 0) { //表示子单
                        Query mainQuery = Query.noPage();
                        mainQuery.put("tableId", 205);
                        mainQuery.put("purId", dto.getId());
                        mainQuery.put("partId", item.getPartId());
                        mainQuery.put("stopFlag", 0);
                        TransportPurchaseDetail mainDTO = purchaseDetailService.selectObjByQuery(mainQuery);

                        //outType：11出库，12退库，13解锁未使用物料
                        if (dto.getOutType() == 11 && mainDTO != null) {
                            //出库：扣减主单出库数量、增加主单实际出库数量
                            //反向操作是：增加主单出库数量，减少主单实际出库数量
                            TransportPurchaseDetail update = new TransportPurchaseDetail();
                            update.setId(mainDTO.getId());
                            update.setcCount(mainDTO.getcCount() + item.getcCount()); //增加主单出库数量
                            update.setcCountReal(mainDTO.getcCountReal() - item.getcCount()); //减少主单实际出库数量
                            purchaseDetailService.updateInfoById(update);
                        }

                        if (dto.getOutType() == 12 && mainDTO != null) {
                            //退库：扣减主单实际出库数量
                            //反向操作是：增加主单实际出库数量
                            TransportPurchaseDetail update = new TransportPurchaseDetail();
                            update.setId(mainDTO.getId());
                            update.setcCountReal(mainDTO.getcCountReal() + item.getcCount()); //增加主单实际出库数量
                            purchaseDetailService.updateInfoById(update);
                        }
                    }
                }
            }
        }

        return isNext;
    }
    //endregion

    //region [10].销售订单
    private Boolean saleOrderApply(WorkflowApply applyDTO, WorkflowApplyLine line_dto, WorkflowApplyLine next_dto, Integer status) {
        Boolean isNext = true;

        //获取销售订单信息
        MesSaleOrder dto = mesSaleOrderService.selectById(applyDTO.getRecordId());
        if (dto == null) {
            return isNext;
        }

        MesSaleOrder updateDTO = new MesSaleOrder();
        updateDTO.setId(applyDTO.getRecordId());

        //[1]. 判断状态：正常审批/驳回/撤回
        if (status == 1) {
            //正常审批
            if (next_dto != null) {
                //这里为什么要更新为下一个节点的状态？
                //因为当前状态已经审批完了，要给用户展示的是下一个节点的信息
                updateDTO.setStatus(next_dto.getRecordStatus());
            } else {
                //最后一个状态为自动节点，审批完更新为当前节点状态即可
                updateDTO.setStatus(line_dto.getRecordStatus());
            }

        } else if (status == -1) {
            //驳回
            updateDTO.setStatus(line_dto.getRejectStatus());

        } else if (status == -10) {
            //撤回
            updateDTO.setStatus(-10);
            updateDTO.setStopFlag(1);

        } else {
            //TODO
        }

        //[2]. 更新状态：正常审批/驳回/撤回
        if (status == 1 || status == -1 || status == -10) {
            isNext = mesSaleOrderService.updateInfoById(updateDTO);
        }

        //[3]. 这里很重要：当审批为“驳回”、“撤回”时，将产品销售记录、客户原料设为无效，否则影响统计
        if (isNext && (status == -1 || status == -10)) {
            Query query = Query.noPage();
            query.put("w_orderId", dto.getId());
            query.put("stopFlag", 1);
            mesSaleOrderDetailService.updateInfoByQuery(query);

            Query materialQuery = Query.noPage();
            materialQuery.put("w_tableId", 203);
            materialQuery.put("w_recordId", dto.getId());
            materialQuery.put("stopFlag", 1);
            mesOrderMaterialService.updateInfoByQuery(materialQuery);
        }

        return isNext;
    }
    //endregion

    //region [11].生产订单审批
    private Boolean produceOrderApply(WorkflowApply applyDTO, WorkflowApplyLine line_dto, WorkflowApplyLine next_dto, Integer status) {
        Boolean isNext = true;

        //获取生产订单信息
        MesProduceOrder dto = mesProduceOrderService.selectById(applyDTO.getRecordId());
        if (dto == null) {
            return isNext;
        }

        MesProduceOrder updateDTO = new MesProduceOrder();
        updateDTO.setId(applyDTO.getRecordId());

        //[1]. 判断状态：正常审批/驳回/撤回
        if (status == 1) {
            //正常审批
            if (next_dto != null) {
                //这里为什么要更新为下一个节点的状态？
                //因为当前状态已经审批完了，要给用户展示的是下一个节点的信息
                updateDTO.setStatus(next_dto.getRecordStatus());
            } else {
                //最后一个状态为自动节点，审批完更新为当前节点状态即可
                updateDTO.setStatus(line_dto.getRecordStatus());
            }

        } else if (status == -1) {
            //驳回
            updateDTO.setStatus(line_dto.getRejectStatus());

        } else if (status == -10) {
            //撤回
            updateDTO.setStatus(-10);
            updateDTO.setStopFlag(1);

        } else {
            //TODO
        }

        //[2]. 更新状态：正常审批/驳回/撤回
        if (status == 1 || status == -1 || status == -10) {
            isNext = mesProduceOrderService.updateInfoById(updateDTO);
        }

        //[3]. 这里很重要：当审批为“驳回”、“撤回”时，将产品销售记录、客户原料设为无效，否则影响统计
        if (isNext && (status == -1 || status == -10)) {
            //删除生产-销售关联明细
            Query query = Query.noPage();
            query.put("w_produceId", dto.getId());
            query.put("deleteFlag", 1);
            mesProduceOrderSaleService.updateInfoByQuery(query);

            //删除订单用料明细
            Query materialQuery = Query.noPage();
            materialQuery.put("w_tableId", 191);
            materialQuery.put("w_recordId", dto.getId());
            materialQuery.put("deleteFlag", 1);
            mesOrderMaterialService.updateInfoByQuery(materialQuery);
        }

        return isNext;
    }
    //endregion

    //endregion

    //region 自动审批【某个环节】【第一个环节】【当前环节】

    /**
     * 自动审批：某个环节
     *
     * @param businessId 流程类型
     * @param applyId    审批ID
     * @param nodeSign   环节标志
     * @param adminId    审批人
     */
    public void autoApply(Integer businessId, Integer applyId, Integer nodeSign, Integer adminId) {
        autoApply(businessId, applyId, nodeSign, "自动审批", adminId);
    }

    public void autoApply(Integer businessId, Integer applyId, Integer nodeSign, String remark, Integer adminId) {
        Integer lineId = applyLineService.getLineIdByNodesign(businessId, applyId, nodeSign);
        if (lineId > 0) {
            approvelApply(lineId, 1, remark, adminId, 0, 0);
        }
    }

    /**
     * 自动审批：第一个环节
     *
     * @param applyId 审批ID
     * @param status  审批状态
     * @param adminId 审批人
     */
    public void autoApplyFirstNode(Integer applyId, Integer status, Integer adminId) {
        Integer lineId = applyLineService.getFirstLineIdByApplyId(applyId);
        if (lineId > 0) {
            approvelApply(lineId, status, "自动审批", adminId, 0, 0);
        }
    }

    /**
     * 自动审批：当前环节
     *
     * @param applyId 审批ID
     * @param status  审批状态
     * @param adminId 审批人
     */
    public void autoApplyCurrNode(Integer applyId, Integer status, Integer adminId) {
        Integer lineId = applyLineService.getCurrLineIdByApplyId(applyId);
        if (lineId > 0) {
            approvelApply(lineId, status, "自动审批", adminId, 0, 0);
        }
    }
    //endregion
}
